#ifndef __POINT4__
#define __POINT4__

#include <exception>

template<typename T>
struct Matrix4;

template<typename T>
struct Point4
{
public:
	inline static const Point4 &UnitX()
	{
		static Point4 _unitx(1, 0, 0, 0);
		return _unitx;
	}

	inline static const Point4 &UnitY()
	{
		static Point4 _unity(0, 1, 0, 0);
		return _unity;
	}
	
	inline static const Point4 &UnitZ()
	{
		static Point4 _unitz(0, 0, 1, 0);
		return _unitz;
	}
	
	inline static const Point4 &UnitW()
	{
		static Point4 _unitw(0, 0, 0, 1);
		return _unitw;
	}

	inline static const Point4 &Zero()
	{
		static Point4 _zero(0, 0, 0, 0);
		return _zero;
	}

	inline static const Point4 &One()
	{
		static Point4 _one(1, 1, 1, 1);
		return _one;
	}

	T X, Y, Z, W;
	
	Point4() :
		X(0),
		Y(0),
		Z(0),
		W(0)
	{
	};

	Point4(const T &x, const T &y, const T &z, const T &w) :
		X(x),
		Y(y),
		Z(z),
		W(w)
	{
	};

	Point4(const Point4 &p) :
		X(p.X),
		Y(p.Y),
		Z(p.Z),
		W(p.W)
	{
	};
	
	T &operator[](const int &index)
	{
		switch (index)
		{
		case 0:
			return X;
		case 1:
			return Y;
		case 2:
			return Z;
		case 3:
			return W;
		}

		throw std::exception();
	}

	const T &operator[](const int &index) const
	{
		switch (index)
		{
		case 0:
			return X;
		case 1:
			return Y;
		case 2:
			return Z;
		case 3:
			return W;
		}

		throw std::exception();
	}

	inline bool operator ==(const Point4 &r) const
	{
		return X == r.X && Y == r.Y && Z == r.Z && W == z.W;
	}

	inline bool operator !=(const Point4 &r) const
	{
		return !operator==(r);
	}
	
	Point4 operator *(const float &r) const
	{
		return Point4(X * r, Y * r, Z * r, W * r);
	}

	inline int CompareTo(const Point4 &r) const
	{
		if (X > r.X)
			return -1;
		if (X < r.X)
			return 1;

		if (Y > r.Y)
			return -1;
		if (Y < r.Y)
			return 1;
		
		if (Z > r.Z)
			return -1;
		if (Z < r.Z)
			return 1;

		if (W > r.W)
			return -1;
		if (W < r.W)
			return 1;

		return 0;
	}

	inline bool operator< (const Point4 &r) const
	{
		return CompareTo(r) == -1;
	}

	inline bool operator> (const Point4 &r) const
	{
		return CompareTo(r) == 1;
	}
};
#endif

typedef Point4<int> Point4i;
typedef Point4<float> Point4f;